<?php
class session{
	private $app;
	private $session = array();
	private $expire = 1209600;
	private $has_change = false;
	
	public function __construct(){
		global $app;
		$app->{"session"} =& $this;
		$this->app =& $app;
		if(! empty($_COOKIE['session_id'])){
			if($res = $app->db->select("sessions", "*", "WHERE `key`='{$_COOKIE['session_id']}'")){
				$this->session = unserialize($res[0]["data"]);
			}else{
				setcookie("session_id", '', time() - $this->expire);
				app_die("找不到您的 session id，有陰謀？ (thinking)<br />請重整網頁");
			}
		}
		$this->gc();
	}
	
	/**
	 * 一定機率會執行清理過期 Session 的動作
	 */
	protected function gc(){
		srand(time());
		if((rand() % 100)< 5){
			$expire = time() - $this->expire;
			if($this->app->db->execute("DELETE FROM `{$this->app->table['sessions']}` WHERE `expire` < '".date("Y-m-d H:i:s", $expire)."'") === false)
				app_die("Session 出問題囉，請聯絡管理員！");
			$this->session = array();
		}
	}
	
	/**
	 * 寫入資料，可輸入字串、陣列
	 * @param mixed $key
	 * @param mixed $data
	 */
	public function write($key, $data){
		$this->has_change = true;
		if(is_array($key)){
			foreach($key as $i => $val)
				$this->write($val, $data[$i]);
		}else
			$this->session[$key] = $data;
	}
	
	/**
	 * 讀取資料，如果沒有給定 $key 值，則回傳整個 Session 陣列
	 * @param string $key
	 */
	public function read($key = null){
		return empty($key)? $this->session: $this->session[$key];
	}
	
	/**
	 * 清除資料，如果沒有給定 $key 值，則清除整個 Session 陣列
	 * @param unknown_type $key
	 */
	public function destroy($key = null){
		$this->has_change = true;
		switch(true){
			case is_array($key):
				foreach($key as $val)
					$this->destroy($val);
				break;
			case is_string($key):
				unset($this->session[$key]);
				break;
			default:
				setcookie("session_id", '', time() - $this->expire);
				$this->session = array();
		}
	}
	
	/**
	 * Session 結束，判斷是否修改過資料，如有修改則將資料寫入資料庫
	 */
	public function close(){
		if($this->has_change){
			if(empty($_COOKIE['session_id'])){
				$session_id = md5(time().rand_word(32));
				$this->app->db->insert("sessions", array("key", "data", "expire"), array($session_id, serialize($this->session), date("Y-m-d H:i:s", time() + $this->expire)));
				setcookie("session_id", $session_id, time() + $this->expire);
			}else
				$this->app->db->update("sessions", array("data"), array(serialize($this->session)), "`key`='{$_COOKIE['session_id']}'");
		}
	}
}
?>